using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Wrath.Xml;
using System.Drawing.Imaging;
using Wrath.RuleForge.Common;
using ICSharpCode.SharpZipLib.Zip;

namespace Wrath.RuleForge
{
    public partial class ModuleManager : Form
    {
        public ModuleManager()
        {
            InitializeComponent();
        }

        private void ModuleManager_Load(object sender, EventArgs e)
        {
            moduleView.Items.Clear();
            moduleThumbnailLarge.Images.Clear();

            for (int i = 0; i < Globals.Modules.Count; i++)
            {
                Globals.ModuleInformation mi = Globals.Modules.GetModule(i);

                AddListItem(mi);
            }
        }

        private void AddListItem(Globals.ModuleInformation mi)
        {
            ListViewGroup group = moduleView.Groups[mi.RuleSet];
            if (group == null)
            {
                group = new ListViewGroup(mi.RuleSet, mi.RuleSet);
                group.Name = mi.RuleSet;
                moduleView.Groups.Add(group);
            }

            ListViewItem newItem = new ListViewItem();
            newItem.Group = group;
            newItem.Name = mi.Filename;
            newItem.Text = mi.Name;
            newItem.ToolTipText = mi.Name;
            newItem.SubItems.Add(mi.Author);
            newItem.SubItems.Add(mi.RuleSet);

            moduleThumbnailLarge.Images.Add(mi.Filename, mi.Thumbnail);
            moduleThumbnailSmall.Images.Add(mi.Filename, mi.Thumbnail);
            newItem.ImageKey = mi.Filename;

            newItem.Tag = mi;

            moduleView.Items.Add(newItem);
        }

        private void largeIconsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            moduleView.View = View.LargeIcon;
            smallIconsToolStripMenuItem.Checked = false;
            listToolStripMenuItem.Checked = false;
            detailsToolStripMenuItem.Checked = false;
            tilesToolStripMenuItem.Checked = false;
            largeIconsToolStripMenuItem.Checked = true;
        }

        private void smallIconsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            moduleView.View = View.SmallIcon;
            largeIconsToolStripMenuItem.Checked = false;
            listToolStripMenuItem.Checked = false;
            detailsToolStripMenuItem.Checked = false;
            tilesToolStripMenuItem.Checked = false;
            smallIconsToolStripMenuItem.Checked = true;
        }

        private void listToolStripMenuItem_Click(object sender, EventArgs e)
        {
            moduleView.View = View.List;
            smallIconsToolStripMenuItem.Checked = false;
            largeIconsToolStripMenuItem.Checked = false;
            detailsToolStripMenuItem.Checked = false;
            tilesToolStripMenuItem.Checked = false;
            listToolStripMenuItem.Checked = true;
        }

        private void detailsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            moduleView.View = View.Details;
            smallIconsToolStripMenuItem.Checked = false;
            listToolStripMenuItem.Checked = false;
            largeIconsToolStripMenuItem.Checked = false;
            tilesToolStripMenuItem.Checked = false;
            detailsToolStripMenuItem.Checked = true;
        }

        private void tilesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            moduleView.View = View.Tile;
            smallIconsToolStripMenuItem.Checked = false;
            listToolStripMenuItem.Checked = false;
            detailsToolStripMenuItem.Checked = false;
            largeIconsToolStripMenuItem.Checked = false;
            tilesToolStripMenuItem.Checked = true;
        }

        private void noneToolStripMenuItem_Click(object sender, EventArgs e)
        {
            moduleView.Sorting = SortOrder.None;
            noneToolStripMenuItem.Checked = true;
            ascendingToolStripMenuItem.Checked = false;
            descendingToolStripMenuItem.Checked = false;
        }

        private void ascendingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            moduleView.Sorting = SortOrder.Ascending;
            noneToolStripMenuItem.Checked = false;
            ascendingToolStripMenuItem.Checked = true;
            descendingToolStripMenuItem.Checked = false;
        }

        private void descendingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            moduleView.Sorting = SortOrder.Descending;
            noneToolStripMenuItem.Checked = false;
            ascendingToolStripMenuItem.Checked = false;
            descendingToolStripMenuItem.Checked = true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void contextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            if (moduleView.SelectedItems.Count < 1)
            {
                e.Cancel = true;
                return;
            }
        }

        private void moduleView_DoubleClick(object sender, EventArgs e)
        {
            if (moduleView.SelectedItems.Count < 1) return;
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (moduleView.SelectedItems.Count < 1) return;

            Globals.ModuleInformation mi = (Globals.ModuleInformation)moduleView.SelectedItems[0].Tag;

            DialogResult result = MessageBox.Show("Deleting a module will permanantly remove it from disk!\n\nAre you sure you want to delete " + mi.Name + "?", "Delete Module", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
            if (result == DialogResult.Yes)
            {
                if (File.Exists(Globals.FantasyGroundsPaths.Modules + "\\" + mi.Filename))
                {
                    // Delete Module
                    File.Delete(Globals.FantasyGroundsPaths.Modules + "\\" + mi.Filename);

                    // Remove from ListView
                    moduleView.Items.Remove(moduleView.SelectedItems[0]);

                    // Remove from Globals
                    Globals.Modules.RemoveModuleByName(mi.Name);

                    // Remove module from Menus
                    MainForm mainForm = (MainForm)FormBroker.GetForm("main");
                    mainForm.RemoveModule(mi);

                    mi.Dispose();

                    // Remove Module Cache
                    if (Directory.Exists(Globals.RuleForgePaths.ModuleCache + "\\" + Path.GetFileNameWithoutExtension(mi.Filename)))
                    {
                        try
                        {
                            // Clear Module Cache
                            Directory.Delete(Globals.RuleForgePaths.ModuleCache + "\\" + Path.GetFileNameWithoutExtension(mi.Filename), true);
                        }
                        catch { }
                    }
                }
            }
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (moduleView.SelectedItems.Count < 1) return;

            Cursor.Current = Cursors.WaitCursor;

            Globals.ModuleInformation oldMi = (Globals.ModuleInformation)moduleView.SelectedItems[0].Tag;

            ModuleInformationEntry modInfoEntry = new ModuleInformationEntry();
            modInfoEntry.ModuleInfo = oldMi;

            DialogResult result = modInfoEntry.ShowDialog(this);
            if (result == DialogResult.OK)
            {
                ProgressDialog progressDialog = new ProgressDialog();
                progressDialog.Title = "Copy Module";
                progressDialog.Show();

                Globals.ModuleInformation newMi = modInfoEntry.ModuleInfo;

                // Get a unique module filename
                progressDialog.CurrentOperation = "Finding unique Module filename...";
                newMi.Filename = newMi.Name.Replace(" ", "").ToLower() + ".mod";
                int copyNumber = 1;
                while (File.Exists(Globals.FantasyGroundsPaths.Modules + "\\" + newMi.Filename))
                {
                    newMi.Filename = newMi.Name.Replace(" ", "").ToLower() + "_" + copyNumber.ToString() + ".mod";
                    copyNumber++;
                }
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Extracting Files...";
                // Extract old module to new cache folder.
                string cachePath = Globals.RuleForgePaths.ModuleCache + "\\" + Path.GetFileNameWithoutExtension(newMi.Filename);

                FastZip zip = new FastZip();
                zip.ExtractZip(Globals.FantasyGroundsPaths.Modules + "\\" + oldMi.Filename, cachePath, "");

                //Zip.ZipHelper.ExtractZipFile(Globals.FantasyGroundsPaths.Modules + "\\" + oldMi.Filename, cachePath);
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Setting Module Information...";
                // Modify definition file
                FileParser definitionFile = new FileParser(cachePath + "\\definition.xml");
                Element nameElement = definitionFile.FindFirstElement("name");
                Element authorElement = definitionFile.FindFirstElement("author");
                Element rulsetElement = definitionFile.FindFirstElement("ruleset");

                nameElement.Value = newMi.Name;
                authorElement.Value = newMi.Author;
                rulsetElement.Value = newMi.RuleSet;

                definitionFile.Save(cachePath + "\\definition.xml", true);
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Finding Data File...";
                // Modify db/client file
                string dataFilename = "";
                if (File.Exists(cachePath + "\\db.xml")) dataFilename = "db.xml";
                else if (File.Exists(cachePath + "\\client.xml")) dataFilename = "client.xml";
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Parsing Data File...";
                FileParser dataFile = new FileParser(cachePath + "\\" + dataFilename);
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Updating Data File: module name...";
                // Update Module Name
                List<Element> names = dataFile.FindAll("name", "type", "string");
                foreach (Element name in names)
                {
                    name.Value = name.Value.Replace(oldMi.Name, newMi.Name);
                }
                progressDialog.Progress = 35;

                progressDialog.CurrentOperation = "Updating Data File: module category...";
                // Update Module Category
                List<Element> categories = dataFile.FindAll("categoryname", "type", "string");
                foreach (Element category in categories)
                {
                    category.Value = category.Value.Replace(oldMi.Category, newMi.Category);
                }
                progressDialog.Progress = 45;

                progressDialog.CurrentOperation = "Updating Module References: recordname fields...";
                // Update DB element references.
                List<Element> records = dataFile.FindAll("recordname");
                foreach (Element record in records)
                {
                    record.Value = record.Value.Replace(oldMi.Name, newMi.Name);
                }
                progressDialog.Progress = 55;

                progressDialog.CurrentOperation = "Updating Module References: recordname attributes...";
                // Update DB attribute references.
                List<Element> attributeRecords = dataFile.FindAllWithAttribute("recordname");
                foreach (Element record in attributeRecords)
                {
                    Wrath.Xml.Attribute recordname = record.FindAttribute("recordname");
                    if (recordname != null)
                    {
                        recordname.Value = recordname.Value.Replace(oldMi.Name, newMi.Name);
                    }
                }
                progressDialog.Progress = 65;

                progressDialog.CurrentOperation = "Updating Module References: formattedtext links...";
                // Update formatted text links.
                List<Element> formattedText = dataFile.FindAllWithAttribute("type", "formattedtext");
                foreach (Element element in formattedText)
                {
                    element.Value = element.Value.Replace("@" + oldMi.Name, "@" + newMi.Name);
                }
                progressDialog.Progress = 75;

                progressDialog.CurrentOperation = "Saving Data File...";
                // Save data file.
                dataFile.Save(cachePath + "\\" + dataFilename, true);
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Saving Thumbnail...";
                // Save Thumbnail.
                newMi.Thumbnail.Save(cachePath + "\\thumbnail.png", ImageFormat.Png);
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Packaging Module...";
                // Create Zip File.
                zip.CreateZip(Globals.FantasyGroundsPaths.Modules + "\\" + newMi.Filename, cachePath + "\\", true, "");
                //Zip.ZipHelper.CreateZipFile(Globals.FantasyGroundsPaths.Modules + "\\" + newMi.Filename, cachePath + "\\", Directory.GetFiles(cachePath));
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Linking Module...";
                // Add to Modules List
                Globals.Modules.AddModule(newMi);
                progressDialog.Increment(5);

                progressDialog.CurrentOperation = "Refreshing View...";
                // Add List Item
                AddListItem(newMi);
                progressDialog.Progress = 100;

                progressDialog.Close();
            }

            Cursor.Current = Cursors.Default;
        }
    }
}